package com.yupi.springbootinit.bizmq;

import com.google.gson.Gson;
import com.rabbitmq.client.Channel;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.constant.AiConstant;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.manager.AiManager;
import com.yupi.springbootinit.model.entity.Chart;
import com.yupi.springbootinit.service.ChartService;
import com.yupi.springbootinit.utils.ChatAiUtils;
import com.yupi.springbootinit.utils.ExcelUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Component
@Slf4j
public class BiMessageConsumer {
    @Resource
    private ChartService chartService;

    @Resource
    private AiManager aiManager;


    @Resource
    private RabbitTemplate rabbitTemplate;


    private final static Gson GSON = new Gson();

    //指定程序监听的消息队列和确认机制
    @SneakyThrows
    @RabbitListener(queues = {BiMqConstant.BI_QUEUE_NAME}, ackMode = "MANUAL")
    public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        log.info("receive message: {}", message);
        if (StringUtils.isBlank(message)) {
            // 消息为空，拒绝
            channel.basicNack(deliveryTag, false, false);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "消息队列传入消息为空，请排查");
        }
        // 更新状态为"running"
        long chartId = Long.parseLong(message);
        Chart chart = chartService.getById(chartId);
        if (chart == null) {
            // 图表不存在，拒绝
            channel.basicNack(deliveryTag, false, false);
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "图表不存在，请排查");
        }
        chart.setStatus("running");
        boolean b = chartService.updateById(chart);
        if (!b) {

            handleChartUpdateError(chart.getId(), "更新图表执行中状态失败");
            return;
        }

        // 执行AI调用等耗时操作
        String aiResult;
        try {
            aiResult = aiManager.doChat(Arrays.asList(
                    ChatAiUtils.Message.system(AiConstant.STSTEM_PROMPT),
                    ChatAiUtils.Message.user(buildUserInput(chart))
            ));
        } catch (Exception e) {
            log.error("调用AI服务失败", e);
            channel.basicNack(deliveryTag, false, false);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "AI服务调用失败，请稍后重试");

        }
        log.info(aiResult);
        // 7. 正则解析 AI 输出
        Pattern pattern = Pattern.compile(
                "``json\\s*([\\s\\S]*?)\\s*```\\s*``text\\s*([\\s\\S]*?)\\s*```",
                Pattern.DOTALL
        );
        Matcher matcher = pattern.matcher(aiResult);
        // 检查是否匹配成功
        if (!matcher.find()) {
            log.error("AI返回内容无法解析：{}", aiResult);
            handleChartUpdateError(chart.getId(), "AI返回内容格式不符合预期");
            channel.basicNack(deliveryTag, false, false);
            return;
        }
        String genChart = matcher.group(1).trim();   // ECharts option JS 代码
        String genResult = matcher.group(2).trim();  // 分析结论文本
        log.info("genChart: " + genChart);
        log.info("genResult: " + genResult);
        // 8. 验证生成的图表代码是否为有效的JSON
        try {
            GSON.fromJson(genChart, Object.class);
        } catch (Exception e) {
            log.error("AI生成的图表代码不是有效的JSON格式：{}", genChart, e);
            chart.setStatus("failed");
            chart.setExecMessage("AI生成的图表代码格式有误，请联系管理员处理");
            boolean updateResult = chartService.updateById(chart);
            if (!updateResult) {
                handleChartUpdateError(chart.getId(), "更新图表失败状态失败");
                return;
            }
            channel.basicNack(deliveryTag, false, false);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "AI生成的图表代码格式有误，请联系管理员处理");

        }
        // ... AI调用逻辑 ...

        // 处理结果并更新状态为"succeed"
        chart.setStatus("succeed");
        chart.setId(chart.getId());
        chart.setGenChart(genChart);
        chart.setGenResult(genResult);
        log.info("成功生成图表，ID: {}, 用户: {}", chart.getId(), chart.getUserId());
        boolean updateResult = chartService.updateById(chart);
        if (!updateResult) {
            handleChartUpdateError(chart.getId(), "更新图表成功状态失败");
        }
        //消息确认
        channel.basicAck(deliveryTag, false);

    }


    /**
     * 构建用户输入
     *
     * @param chart
     * @return
     */
    private String buildUserInput(Chart chart) {
        // 3. 构造用户输入（用于发送给 AI）
        String goal = chart.getGoal();
        String chartType = chart.getChartType();
        String csvData = chart.getChartData();
        StringBuilder userInput = new StringBuilder();
        userInput.append("分析需求：\n").append(goal).append("\n");
        if (StringUtils.isNotBlank(chartType)) {
            userInput.append("图表类型：").append(chartType).append("\n");
        }
        
        // 限制数据长度，防止超出模型最大序列长度
        String dataHeader = "原始数据：\n";
        int maxDataLength = 30000; // 保留一些空间给其他内容
        if (csvData.length() > maxDataLength) {
            log.warn("数据过长，进行截断处理。原始长度: {}, 截断后长度: {}", csvData.length(), maxDataLength);
            csvData = csvData.substring(0, maxDataLength);
        }
        userInput.append(dataHeader).append(csvData);
        return userInput.toString();
    }

    private void handleChartUpdateError(long chartId, String execMessage) {
        Chart updateChart = new Chart();
        updateChart.setId(chartId);
        updateChart.setStatus("failed");
        updateChart.setExecMessage(execMessage);
        boolean updateResult = chartService.updateById(updateChart);
        if (!updateResult) {
            log.error("更新图表失败：{}", chartId + "," + execMessage);
        }
    }
}